package com.fsnbigdata.web;
import com.fsnbigdata.domain.Document;
import com.fsnbigdata.domain.Specimen;
import com.fsnbigdata.enums.ResultEnum;
import com.fsnbigdata.exception.ParamException;
import com.fsnbigdata.service.api.DocumentService;
import com.fsnbigdata.util.ReflectUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;

import java.lang.reflect.Method;
import java.security.Principal;
import java.util.Set;
import java.util.stream.Collectors;

import io.swagger.annotations.ApiOperation;
import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType;
import org.springframework.roo.addon.web.mvc.controller.annotations.RooController;
import org.springframework.roo.addon.web.mvc.controller.annotations.responses.json.RooJSON;
import com.fsnbigdata.service.api.SpecimenService;
import io.springlets.web.NotFoundException;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.util.UriComponents;
import springfox.documentation.annotations.ApiIgnore;

/**
 * = SpecimensItemJsonController
 *
 * TODO Auto-generated class documentation
 *
 */
@RooController(entity = Specimen.class, pathPrefix = "/api", type = ControllerType.ITEM)
@RooJSON
@RestController
@RequestMapping(value = "/api/specimens/{id}", name = "SpecimensItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "Specimen", description = "标本" )
public class SpecimensItemJsonController {

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private SpecimenService specimenService;

    private DocumentService documentService;

    /**
     * TODO Auto-generated constructor documentation
     *
     * @param specimenService
     */
    @Autowired
    public SpecimensItemJsonController(SpecimenService specimenService,DocumentService documentService) {
        this.specimenService = specimenService;
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return SpecimenService
     */
    public SpecimenService getSpecimenService() {
        return specimenService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param specimenService
     */
    public void setSpecimenService(SpecimenService specimenService) {
        this.specimenService = specimenService;
    }

    public DocumentService getDocumentService() {
        return documentService;
    }

    public void setDocumentService(DocumentService documentService) {
        this.documentService = documentService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param id
     * @return Specimen
     */
    @ModelAttribute
    public Specimen getSpecimen(@PathVariable("id") Long id) {
        Specimen specimen = specimenService.findOne(id);
        if (specimen == null) {
            throw new NotFoundException(String.format("Specimen with identifier '%s' not found", id));
        }
        return specimen;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param specimen
     * @return ResponseEntity
     */
    @GetMapping(name = "show")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    //@PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> show(@ApiIgnore @ModelAttribute Specimen specimen) {
        return ResponseEntity.ok(specimen);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param specimen
     * @return UriComponents
     */
    public static UriComponents showURI(Specimen specimen) {
        return MvcUriComponentsBuilder.fromMethodCall(MvcUriComponentsBuilder.on(SpecimensItemJsonController.class).show(specimen)).buildAndExpand(specimen.getId()).encode();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param storedSpecimen
     * @param specimen
     * @param result
     * @return ResponseEntity
     */
    @PutMapping(name = "update")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    @PreAuthorize("hasRole('DB_SPECIMEN')")
    @ApiOperation(value = "",notes = "update")
    public ResponseEntity<?> update(
        @ApiIgnore @ModelAttribute Specimen storedSpecimen,
        @Valid @RequestBody Specimen specimen,
        BindingResult result,
        Principal principal) throws Exception {
        if (result.hasErrors()) {
            throw new ParamException(ResultEnum.PARAM_ERROR.getCode(),
                    result.getFieldError().getDefaultMessage());
        }

        specimen.setId(storedSpecimen.getId());

        Set<Document> toSaveDocs = specimen.getDocs();
        specimen.setDocs(storedSpecimen.getDocs());
        String name = getSpecimenService().findOne(storedSpecimen.getId()).getName();
        Specimen retval = getSpecimenService().save(specimen);

        Set<Long> docIds = toSaveDocs.stream().map(doc -> {
            if(doc.getId() == null) {
                doc.setCreator(principal.getName());
                getDocumentService().save(doc);
                return doc.getId();
            }else{
                return doc.getId();
            }
        }).collect(Collectors.toSet());

        getSpecimenService().setDocs(retval, docIds);
        Class<?> clazz = SpecimensItemJsonController.class;
        Method method = clazz.getMethod("update", ReflectUtil.getPeremeterClass(clazz, "update"));
        ReflectUtil.setAnnotationOn(method,"更新标本库，中文名："+name);
        return ResponseEntity.ok(retval);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param specimen
     * @return ResponseEntity
     */
    @DeleteMapping(name = "delete")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "", paramType = "path", dataType = "int", required = true)
    })
    @PreAuthorize("hasRole('DB_SPECIMEN')")
    @ApiOperation(value = "",notes = "delete")
    public ResponseEntity<?> delete(@ApiIgnore @ModelAttribute Specimen specimen) throws Exception {
        getSpecimenService().delete(specimen);
        Class<?> clazz = SpecimensItemJsonController.class;
        Method method = clazz.getMethod("delete", ReflectUtil.getPeremeterClass(clazz, "delete"));
        ReflectUtil.setAnnotationOn(method,"删除标本库，中文名："+specimen.getName());
        return ResponseEntity.ok().build();
    }
}
